﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraBars;
using CTEM.Controllers.BUS;
using CTEM.Models;
using CTEM.Controllers.Global;
using DevExpress.XtraEditors;
using CTEM.Controllers.Global;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraEditors.DXErrorProvider;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid;

namespace CTEM.ModuleForms.ManageWarehouse
{
    public partial class WarehouseManagement : DevExpress.XtraBars.Ribbon.RibbonForm
    {
        private readonly WarehouseBUS _warehouseBUS = new WarehouseBUS();
        private List<WH_WarehouseDTO> _listWarehouses = new List<WH_WarehouseDTO>();
        private readonly List<WH_WarehouseDTO> _listHistory = new List<WH_WarehouseDTO>();
        private bool _isNew;
        private bool _isAllowEdit;
        public WarehouseManagement()
        {
            InitializeComponent();
        }

        private void WarehouseManagement_Load(object sender, EventArgs e)
        {
            _isAllowEdit = true;
            AllowEditorNot();
            LoadRepositoryItems();
            LoadActiveWarehouse();
        }

        private void barButtonItemLoadAll_ItemClick(object sender, ItemClickEventArgs e)
        {
            LoadRepositoryItems();
            LoadAllWarehouse();
        }

        private void barButtonItemRefresh_ItemClick(object sender, ItemClickEventArgs e)
        {
            LoadRepositoryItems();
            LoadActiveWarehouse();
        }


        private void barButtonItemDelete_ItemClick(object sender, ItemClickEventArgs e)
        {
            DeleteWarehouse();
        }

        private void barButtonItemDisable_ItemClick(object sender, ItemClickEventArgs e)
        {
            DisableWarehouse();
        }

        private void barButtonItemUndo_ItemClick(object sender, ItemClickEventArgs e)
        {
            Undo();
        }

        private void barButtonItemRedo_ItemClick(object sender, ItemClickEventArgs e)
        {
            Redo();
        }

        /// <summary>
        /// Allow User can edit or not
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void barButtonItemAllowEdit_ItemClick(object sender, ItemClickEventArgs e)
        {
            AllowEditorNot();
        }

        /// <summary>
        /// Always allow User add new construction when allow edit or disable edit
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridViewConstruction_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
        {
            if (e.FocusedRowHandle == GridControl.NewItemRowHandle)
            {
                gridViewWarehouse.OptionsBehavior.ReadOnly = false;
            }
            else
            {
                gridViewWarehouse.OptionsBehavior.ReadOnly = !_isAllowEdit;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridViewWarehouse_InitNewRow(object sender, InitNewRowEventArgs e)
        {
            _isNew = true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridViewWarehouse_InvalidRowException(object sender, InvalidRowExceptionEventArgs e)
        {
            e.ExceptionMode = ExceptionMode.NoAction;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridViewWarehouse_ValidateRow(object sender, ValidateRowEventArgs e)
        {
            if (_isNew)
            {
                ColumnView view = sender as ColumnView;
                WH_WarehouseDTO warehouseDTO = e.Row as WH_WarehouseDTO;
                string errorMessage;
                string fieldName;
                if (_warehouseBUS.ValidateWarehouse(warehouseDTO, out errorMessage, out fieldName))
                {
                    long warehouseID = _warehouseBUS.CreateWarehouse(warehouseDTO);
                    if (warehouseID == 0)
                    {
                        alertControlMain.Show(this, Constants.ALERT_ERROR, Constants.CREATE_FAIL);
                    }
                    else
                    {
                        alertControlMain.Show(this, Constants.CONFIRM, String.Format("Bạn Đã Tạo Kho {0} Thành Công!",warehouseDTO.WarehouseName));
                        RemoveRedoHistory();
                        warehouseDTO.WarehouseID = warehouseID;
                        warehouseDTO.History = HistoryLevel.ADD;
                        _listHistory.Add(warehouseDTO);
                    }
                    _isNew = false;
                    LoadActiveWarehouse();
                }
                else
                {
                    e.Valid = false;
                    view.ClearColumnErrors();
                    view.SetColumnError(view.Columns[fieldName], errorMessage, ErrorType.Warning);
                    DialogResult result = XtraMessageBox.Show(errorMessage + "\nBạn có muốn nhập lại thông tin?", Constants.CONFIRM, MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (result == DialogResult.No)
                    {
                        _isNew = false;
                        e.Valid = true;
                        LoadActiveWarehouse();
                    }
                    else
                    {
                        view.FocusedColumn = view.Columns[fieldName];
                    }
                }
            }
            else
            {
                LoadActiveWarehouse();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridViewWarehouse_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (!_isNew)
            {
                ColumnView view = sender as ColumnView;
                int currentRow = e.RowHandle;
                WH_WarehouseDTO warehouseDTO = gridViewWarehouse.GetRow(currentRow) as WH_WarehouseDTO;
                WH_WarehouseDTO backupCons = _warehouseBUS.GetWarehouseByID(warehouseDTO.WarehouseID);
                string errorMessage;
                string fieldName;
                if (_warehouseBUS.ValidateWarehouse(warehouseDTO, out errorMessage, out fieldName))
                {
                    bool success = _warehouseBUS.UpdateWarehouse(warehouseDTO);
                    if (!success)
                    {
                        alertControlMain.Show(this, Constants.ALERT_ERROR, Constants.UPDATE_FAIL);
                    }
                    else
                    {
                        alertControlMain.Show(this, Constants.CONFIRM, String.Format("Bạn Đã Cập Nhật Thông Tin Kho {0} Thành Công!", warehouseDTO.WarehouseName));
                        RemoveRedoHistory();
                        backupCons.History = HistoryLevel.EDIT;
                        _listHistory.Add(backupCons);
                    }
                    _isNew = false;
                    LoadActiveWarehouse();
                }
                else
                {
                    view.ClearColumnErrors();
                    view.SetColumnError(view.Columns[fieldName], errorMessage, ErrorType.Warning);
                    DialogResult result = XtraMessageBox.Show(errorMessage + "\nBạn có muốn nhập lại thông tin?", Constants.CONFIRM, MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (result == DialogResult.No)
                    {
                        LoadActiveWarehouse();
                    }
                    else
                    {
                        view.FocusedColumn = view.Columns[fieldName];
                        return;
                    }
                }
            }
        }

        /// <summary>
        /// Load Data for Reporsity Items:
        ///     - Repository Construction
        /// </summary>
        private void LoadRepositoryItems()
        {
            ConstructionBUS consBUS = new ConstructionBUS();
            cSConstructionDTOBindingSource.DataSource = consBUS.LoadConstruction(false);
        }

        /// <summary>
        /// Load active warehouse
        /// </summary>
        private void LoadActiveWarehouse()
        {
            LoadWarehouse(true);
        }

        /// <summary>
        /// Load both active and inactive warehouse
        /// </summary>
        private void LoadAllWarehouse()
        {
            LoadWarehouse(false);
        }

        /// <summary>
        /// Function is called to load warehouses
        /// </summary>
        /// <param name="isactive">Load all warehouse or just active warehouse</param>
        private void LoadWarehouse(bool isactive)
        {
            _listWarehouses = _warehouseBUS.LoadWarehouse(isactive);
            wHWarehouseDTOBindingSource.DataSource = _listWarehouses;
        }

        /// <summary>
        /// Allow User Edit Data
        /// </summary>
        private void AllowEditorNot()
        {
            if (_isAllowEdit)
            {
                alertControlMain.Show(this, Constants.CONFIRM, Constants.DISABLE_EIT_MESSAGE);
                _isAllowEdit = false;
                gridViewWarehouse.OptionsBehavior.ReadOnly = true;
                barButtonItemAllowEdit.Caption = Constants.ALLOW_EIT;
            }
            else
            {
                DialogResult result = XtraMessageBox.Show(Constants.ALLOW_EIT_MESSAGE, Constants.CONFIRM, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (result == DialogResult.Yes)
                {
                    _isAllowEdit = true;
                    gridViewWarehouse.OptionsBehavior.ReadOnly = false;
                    barButtonItemAllowEdit.Caption = Constants.DISABLE_EIT;
                }
            }
        }

        /// <summary>
        /// Delete Warehouse Forever Without Construction's warehouse
        /// </summary>
        private void DeleteWarehouse()
        {
            int[] numOfSelectedRows = gridViewWarehouse.GetSelectedRows();
            if (numOfSelectedRows.Length > 0)
            {
                WH_WarehouseDTO warehouseDTO = gridViewWarehouse.GetRow(numOfSelectedRows[0]) as WH_WarehouseDTO;
                if (warehouseDTO.ConstructionID == 0)
                {
                    DialogResult result = XtraMessageBox.Show(String.Format("Nếu Xóa Kho {0} Thì Toàn Bộ Dữ Liệu Liên Quan Sẽ Đều Bị Xóa Bỏ!\nBạn Có Chắc Muốn Xóa Vĩnh Viễn Kho Này Không?", warehouseDTO.WarehouseName), Constants.ALERT, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (result == DialogResult.Yes)
                    {
                        WH_WarehouseDTO backupWarehouse = _warehouseBUS.GetWarehouseByID(warehouseDTO.WarehouseID);
                        warehouseDTO.IsDelete = true;
                        bool success = _warehouseBUS.UpdateWarehouse(warehouseDTO);
                        if (!success)
                        {
                            alertControlMain.Show(this, Constants.ALERT_ERROR, String.Format("Không Thể Xóa Kho {0} Thành Công!", warehouseDTO.WarehouseName));
                        }
                        else
                        {
                            alertControlMain.Show(this, Constants.CONFIRM, String.Format("Bạn Đã Xóa Kho {0} Thành Công!", warehouseDTO.WarehouseName));
                            RemoveRedoHistory();
                            backupWarehouse.History = HistoryLevel.EDIT;
                            _listHistory.Add(backupWarehouse);
                        }
                    }   
                }
                else
                {
                    XtraMessageBox.Show("Đây Là Kho Thuộc Công Trình, Kho Sẽ Tự Xóa Khi Bạn Xóa Công Trình", Constants.CONFIRM, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                
            }
            LoadActiveWarehouse();
        }

        /// <summary>
        /// Disable selected warehouse to inactive it
        /// </summary>
        private void DisableWarehouse()
        {
            int[] numOfSelectedRows = gridViewWarehouse.GetSelectedRows();
            if (numOfSelectedRows.Length > 0)
            {
                WH_WarehouseDTO warehouseDTO = gridViewWarehouse.GetRow(numOfSelectedRows[0]) as WH_WarehouseDTO;
                DialogResult result = XtraMessageBox.Show(String.Format("Vô Hiệu Hóa Kho {0} Thì Chương Trình Sẽ Vô Hiệu Hóa Tất Cả Dữ Liệu Liên Quan Đến Nó!\nBạn Có Chắc Muốn Vô Hiệu Hóa Kho Này Không?", warehouseDTO.WarehouseName), Constants.ALERT, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                if (result == DialogResult.Yes)
                {
                    WH_WarehouseDTO backupwarehouse= warehouseDTO;
                    warehouseDTO.IsActive = false;
                    bool success = _warehouseBUS.UpdateWarehouse(warehouseDTO);
                    if (!success)
                    {
                        alertControlMain.Show(this, Constants.ALERT_ERROR, String.Format("Không Thể Vô Hiệu Hóa Kho {0} Thành Công!", warehouseDTO.WarehouseName));
                    }
                    else
                    {
                        alertControlMain.Show(this, Constants.CONFIRM, String.Format("Bạn Đã Vô Hiệu Hóa Kho {0} Thành Công!\nBạn Có Thể Khôi Phục Lại Bằng Cách Vào Menu Edit/Load All Và Tích Vào Phần Hoạt Động Của Công Trình", warehouseDTO.WarehouseName));
                        RemoveRedoHistory();
                        backupwarehouse.History = HistoryLevel.EDIT;
                        _listHistory.Add(backupwarehouse);
                    }
                }
            }
            LoadActiveWarehouse();
        }

        /// <summary>
        /// After undo, item will change status to waiting for redo.
        /// But after new action work, all items wating for redo must be remove
        /// </summary>
        private void RemoveRedoHistory()
        {
            for (int i = 0; i < _listHistory.Count; i++)
            {
                var warehouse = _listHistory[i];
                if (warehouse.History.ToString().Contains(Constants.UNDO))
                {
                    _listHistory.Remove(warehouse);
                    i--;
                }
            }
        }

        /// <summary>
        /// Undo user action
        /// </summary>
        private void Undo()
        {
            int numHistoryItems = _listHistory.Count;
            for (int i = numHistoryItems; i > 0; i--)
            {
                var undoItem = _listHistory[i - 1];
                switch (undoItem.History)
                {
                    case HistoryLevel.ADD:
                        _warehouseBUS.DeleteWarehouse(undoItem.WarehouseID);
                        _listHistory[i - 1].History = HistoryLevel.UNDO_ADD;
                        LoadActiveWarehouse();
                        return;
                    case HistoryLevel.EDIT:
                        
                        _listHistory[i - 1] = _warehouseBUS.GetWarehouseByID(undoItem.WarehouseID);
                        _listHistory[i - 1].History = HistoryLevel.UNDO_EDIT;
                        _warehouseBUS.UpdateWarehouse(undoItem);
                        LoadActiveWarehouse();
                        return;
                    case HistoryLevel.DELETE:
                        long oldWarehouseID = _listHistory[i - 1].WarehouseID;
                        long newWarehouseID = _warehouseBUS.CreateWarehouse(undoItem);
                        if (newWarehouseID != 0)
                        {
                            foreach (var item in _listHistory)
                            {
                                if (item.WarehouseID == oldWarehouseID)
                                {
                                    item.WarehouseID = newWarehouseID;
                                }
                            }
                            _listHistory[i - 1].History = HistoryLevel.UNDO_DELETE;
                        }
                        LoadActiveWarehouse();
                        return;
                    case HistoryLevel.UNDO_ADD:
                        break;
                    case HistoryLevel.UNDO_EDIT:
                        break;
                    case HistoryLevel.UNDO_DELETE:
                        break;
                }
            }
        }

        /// <summary>
        /// Redo user action
        /// </summary>
        private void Redo()
        {
            int numHistoryItems = _listHistory.Count;
            for (int i = 0; i < numHistoryItems; i++)
            {
                var redoItem = _listHistory[i];
                switch (redoItem.History)
                {
                    case HistoryLevel.ADD:
                        break;
                    case HistoryLevel.EDIT:
                        break;
                    case HistoryLevel.DELETE:
                        break; ;
                    case HistoryLevel.UNDO_ADD:
                        long oldWarehouseID = _listHistory[i].WarehouseID;
                        long newWarehouseID = _warehouseBUS.CreateWarehouse(redoItem);
                        if (newWarehouseID != 0)
                        {
                            foreach (var item in _listHistory)
                            {
                                if (item.WarehouseID == oldWarehouseID)
                                {
                                    item.WarehouseID = newWarehouseID;
                                }
                            }
                            _listHistory[i].History = HistoryLevel.UNDO_DELETE;
                        }
                        LoadActiveWarehouse();
                        return;
                    case HistoryLevel.UNDO_EDIT:
                        _listHistory[i] = _warehouseBUS.GetWarehouseByID(redoItem.WarehouseID);
                        _listHistory[i].History = HistoryLevel.EDIT;
                        _warehouseBUS.UpdateWarehouse(redoItem);
                        LoadActiveWarehouse();
                        return;
                    case HistoryLevel.UNDO_DELETE:
                        _warehouseBUS.DeleteWarehouse(redoItem.ConstructionID);
                        _listHistory[i].History = HistoryLevel.DELETE;
                        LoadActiveWarehouse();
                        return;
                }
            }
        }
    }
}